home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / loadavg / RCS / loadavg.c,v < prev    next >
Encoding:
Text File  |  1990-09-24  |  27.8 KB  |  1,207 lines

  1. head     1.13;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.13
  10. date     90.09.24.14.37.42;  author douglis;  state Exp;
  11. branches ;
  12. next     1.12;
  13.  
  14. 1.12
  15. date     90.06.29.11.24.01;  author douglis;  state Exp;
  16. branches ;
  17. next     1.11;
  18.  
  19. 1.11
  20. date     90.04.09.10.17.46;  author douglis;  state Exp;
  21. branches ;
  22. next     1.10;
  23.  
  24. 1.10
  25. date     89.08.22.22.58.47;  author douglis;  state Exp;
  26. branches ;
  27. next     1.9;
  28.  
  29. 1.9
  30. date     89.07.31.17.51.58;  author douglis;  state Exp;
  31. branches ;
  32. next     1.8;
  33.  
  34. 1.8
  35. date     89.07.13.23.24.42;  author douglis;  state Exp;
  36. branches ;
  37. next     1.7;
  38.  
  39. 1.7
  40. date     89.06.15.22.54.53;  author douglis;  state Exp;
  41. branches ;
  42. next     1.6;
  43.  
  44. 1.6
  45. date     89.05.04.15.49.03;  author douglis;  state Exp;
  46. branches ;
  47. next     1.5;
  48.  
  49. 1.5
  50. date     89.03.17.12.42.17;  author douglis;  state Exp;
  51. branches ;
  52. next     1.4;
  53.  
  54. 1.4
  55. date     88.12.21.16.01.05;  author douglis;  state Exp;
  56. branches ;
  57. next     1.3;
  58.  
  59. 1.3
  60. date     88.11.19.15.54.09;  author douglis;  state Exp;
  61. branches ;
  62. next     1.2;
  63.  
  64. 1.2
  65. date     88.11.15.12.14.08;  author douglis;  state Exp;
  66. branches ;
  67. next     1.1;
  68.  
  69. 1.1
  70. date     88.11.14.13.28.37;  author douglis;  state Exp;
  71. branches ;
  72. next     ;
  73.  
  74.  
  75. desc
  76. @Program for keeping track of the migration database.  See RCS/loadAvg.c,v
  77. for earlier comments.
  78. @
  79.  
  80.  
  81. 1.13
  82. log
  83. @print hasmig + "*" if in use for background job.
  84. @
  85. text
  86. @/*
  87.  * loadavg.c --
  88.  *
  89.  *    Provide access to the load average information database.  
  90.  *
  91.  * Copyright 1990 Regents of the University of California
  92.  * Permission to use, copy, modify, and distribute this
  93.  * software and its documentation for any purpose and without
  94.  * fee is hereby granted, provided that the above copyright
  95.  * notice appear in all copies.  The University of California
  96.  * makes no representations about the suitability of this
  97.  * software for any purpose.  It is provided "as is" without
  98.  * express or implied warranty.
  99.  */
  100.  
  101. #ifndef lint
  102. static char rcsid[] = "$Header: /sprite/src/cmds/loadavg/RCS/loadavg.c,v 1.12 90/06/29 11:24:01 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  103. #endif not lint
  104.  
  105.  
  106. #include <sprite.h>
  107. #include <stdio.h>
  108. #include <stdlib.h>
  109. #include <mig.h>
  110. #include <kernel/net.h>
  111. #include <option.h>
  112. #include <host.h>
  113. #include <syslog.h>
  114. #include <sys/time.h>
  115. #include <sysStats.h>
  116.  
  117. /*
  118.  * Define constants for defaults values of variables that may be assigned
  119.  * by command-line arguments.
  120.  */
  121.  
  122. int allHosts = 0;
  123. int getLoad = 0;
  124. int debug = 0;
  125. int zapHostInfo = 0;
  126. int forceEvict = 0;
  127. int stripDomain = 1;
  128.  
  129. Option optionArray[] = {
  130.     {OPT_TRUE, "l", (char *)&getLoad,
  131.          "Get the load average of this node (DEFAULT)."},
  132.     {OPT_TRUE, "a", (char *)&allHosts,
  133.          "Get the load average of all nodes."},
  134.     {OPT_FALSE, "S", (char *)&stripDomain,
  135.          "Don't strip the domain from host names."},
  136.     {OPT_TRUE, "E", (char *)&forceEvict, "Evict foreign processes immediately."},
  137.     {OPT_TRUE, "D", (char *)&debug, "Enable debugging information."},
  138.     {OPT_TRUE, "Z", (char *)&zapHostInfo,
  139.          "Zap (remove) the information for hosts specified as remaining arguments."},
  140. };
  141. static int numOptions = sizeof(optionArray) / sizeof(Option);
  142.  
  143. /*
  144.  * Global variables.
  145.  */
  146. struct timeval currentTime;
  147. int hostID;
  148. #define HOST_NAME_LENGTH 64
  149. char hostname[HOST_NAME_LENGTH];
  150. char *machType;
  151. char *myName = NULL;
  152. int migVersion;
  153. int kernelState;
  154.  
  155.  
  156. static void ListHosts();
  157. static void OutputStatus();
  158. static void ZapHostInfo();
  159. extern char *rindex();
  160.  
  161.  
  162. /*
  163.  *----------------------------------------------------------------------
  164.  *
  165.  * Main --
  166.  *
  167.  *    The driver for the loadavg program.  Parse options and invoke
  168.  *    subroutines as appropriate.
  169.  *
  170.  * Results:
  171.  *    None.
  172.  *
  173.  * Side effects:
  174.  *    Initializes global variables.
  175.  *
  176.  *----------------------------------------------------------------------
  177.  */
  178.  
  179. int
  180. main(argc, argv)
  181.     int argc;
  182.     char *argv[];
  183. {
  184.     int status;
  185.     int numScanned;
  186.     int i;
  187.     int host;
  188.     Mig_Info *infoPtr;
  189.     Host_Entry *hostPtr;
  190.     
  191.  
  192.     argc = Opt_Parse(argc, argv, optionArray, numOptions,
  193.                OPT_ALLOW_CLUSTERING);
  194.  
  195.     myName = rindex(argv[0], '/');
  196.     if (myName){
  197.     myName++;
  198.     } else {
  199.     myName = argv[0];
  200.     }
  201.  
  202.     /*
  203.      * Process interrelated defaults and perform sanity checking on
  204.      * arguments.
  205.      */
  206.  
  207.     /*
  208.      * Default operation is to get the local load.
  209.      */
  210.  
  211.     if (! (getLoad || allHosts || zapHostInfo || forceEvict)) {
  212.     if (!strcmp(myName, "rup")) {
  213.         allHosts = 1;
  214.     } else if (!strcmp(myName, "evict")) {
  215.         forceEvict = 1;
  216.     } else {
  217.         getLoad = 1;
  218.     }
  219.     }
  220.  
  221.     /*
  222.      * Initialize global variables.
  223.      */
  224.     if (gethostname(hostname, sizeof(hostname)) < 0) {
  225.     perror("gethostname");
  226.     exit(1);
  227.     }
  228.     hostPtr = Host_ByName(hostname);
  229.     if (hostPtr == (Host_Entry *) NULL) {
  230.     fprintf(stderr, "error getting host information for '%s'.\n",
  231.            myName);
  232.     exit(1);
  233.     }
  234.     hostID = hostPtr->id;
  235.     machType = malloc((unsigned) strlen(hostPtr->machType) + 1);
  236.     if (machType == (char *) NULL) {
  237.     panic("Out of memory");
  238.     }
  239.     (void) strcpy(machType, hostPtr->machType);
  240.     
  241.     /*
  242.      * Get our migration version.
  243.      */
  244.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_GET_VERSION,
  245.                (Address) &migVersion);
  246.     if (status != SUCCESS) {
  247.     fprintf(stderr, "Error in Sys_Stats getting migration version: %s\n",
  248.         Stat_GetMsg(status));
  249.     exit(Compat_MapCode(status));
  250.     }
  251.     /*
  252.      * Get the kernel's idea of what we're importing and exporting.
  253.      */
  254.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_GET_STATE,
  255.                (Address) &kernelState);
  256.     if (status != SUCCESS) {
  257.     (void) fprintf(stderr,
  258.                "%s: warning: error in Sys_Stats getting migration state.\n",
  259.                myName);
  260.     kernelState = PROC_MIG_ALLOW_DEFAULT;
  261.     }
  262.     if (debug) {
  263.         (void) fprintf(stderr,
  264.                "My hostID is %d.  machType is %s.  kernel state is 0x%x.\n",
  265.                hostID, machType, kernelState);
  266.     }
  267.     status = gettimeofday(¤tTime, (struct timezone *) NULL);
  268.     if (status == -1) {
  269.     perror("Error in gettimeofday");
  270.     exit(1);
  271.     }
  272.  
  273.     if (zapHostInfo) {
  274.     for (i = 1; i < argc; i++) {
  275.         ZapHostInfo(argv[i]);
  276.     }
  277.     }
  278.     if (allHosts) {
  279.     ListHosts();
  280.     } else if (getLoad) {
  281.     infoPtr = Mig_GetInfo((int) PROC_MY_HOSTID);
  282.     if (infoPtr == (Mig_Info *) NULL) {
  283.         perror("Error in Mig_GetInfo");
  284.         exit(1);
  285.     }
  286.     OutputStatus(infoPtr);
  287.     }
  288.  
  289.     if (forceEvict) {
  290.     int numEvicted = Mig_Evict();
  291.     if (numEvicted < 0) {
  292.         perror("Mig_Evict");
  293.     } else {
  294.         printf("Evicted %d foreign processes.\n", numEvicted);
  295.     }
  296.     }
  297.     exit(0);
  298. }
  299.  
  300.  
  301. /*
  302.  *----------------------------------------------------------------------
  303.  *
  304.  * ListHosts --
  305.  *
  306.  *    Output the load average and status of all nodes.
  307.  *
  308.  * Results:
  309.  *    None.
  310.  *
  311.  * Side effects:
  312.  *    The data are is written to stdout.
  313.  *
  314.  *----------------------------------------------------------------------
  315.  */
  316.  
  317. static void
  318. ListHosts()
  319. {
  320.     int numRecs;
  321.     register Mig_Info *infoPtr;
  322.     Mig_Info *infoArray;
  323.     int i;
  324.     int maxSize;
  325.     int hostID;
  326.     int status;
  327.  
  328.     if (debug) {
  329.     (void) fprintf(stderr, "ListHosts called.\n");
  330.      (void) fflush(stderr);
  331.     }
  332.  
  333.     i = gettimeofday(¤tTime, (struct timezone *) NULL);
  334.     if (i == -1) {
  335.     perror("Error in gettimeofday");
  336.     exit(1);
  337.     }
  338.  
  339.     maxSize = NET_NUM_SPRITE_HOSTS * sizeof(Mig_Info);
  340.     infoArray = (Mig_Info *) malloc((unsigned) maxSize);
  341.     numRecs = Mig_GetAllInfo(infoArray, NET_NUM_SPRITE_HOSTS);
  342.     if (numRecs < 0) {
  343.     perror("Error in Mig_GetAllInfo");
  344.     exit(1);
  345.     }
  346.     if (debug && numRecs == 0) {
  347.     (void) fprintf(stderr, "No host records found.\n");
  348.      (void) fflush(stderr);
  349.     return;
  350.     }
  351.     
  352.     printf("            HOST     TYPE      STATUS       MIG     LOAD AVERAGE   IDLE TIME\n");
  353.  
  354.     for (i = 0; i < numRecs; i++) {
  355.     OutputStatus(&infoArray[i]);
  356.     }
  357.     free((char *) infoArray);
  358. }
  359.  
  360.  
  361. /*
  362.  *----------------------------------------------------------------------
  363.  *
  364.  * OutputStatus --
  365.  *
  366.  *    Determine the status of the given host and write a "ruptime"-like
  367.  *    record to stdout.
  368.  *
  369.  * Results:
  370.  *    None.
  371.  *
  372.  * Side effects:
  373.  *    None.
  374.  *
  375.  *----------------------------------------------------------------------
  376.  */
  377.  
  378. /*
  379.  * Size of the buffer for the current host's name.
  380.  */
  381. #define HOST_NAME_SIZE 64
  382.  
  383. /*
  384.  * Size of the buffer for reporting up- or down-time.
  385.  */
  386. #define TIME_STR_LEN 13
  387.  
  388. /*
  389.  * For Time_ToAscii, if relative time is specified, the time value is
  390.  * interpreted as the difference between two absolute time values and
  391.  * has the form:
  392.  *        0 days, 02:45:09
  393.  *                 ^^^
  394.  * SECOND_OFFSET is used to hide the seconds field by overwriting the colon
  395.  * with a null character.
  396.  */
  397. #define SECOND_OFFSET 9
  398.  
  399. static void
  400. OutputStatus(infoPtr)
  401.     register Mig_Info *infoPtr;
  402. {
  403.     int state;
  404.     char idleTime[TIME_STR_LEN];
  405.     char *idlePtr;
  406.     char timeStr[TIME_STR_LEN];
  407.     char upStr[5];
  408.     char stateStr[8];
  409.     char migOK;
  410.     char hostName[HOST_NAME_SIZE];
  411.     register char *hp;
  412.     register char *sp;
  413.     register int i;
  414.     int diff;
  415.     Host_Entry *hostPtr;
  416.  
  417.     hostPtr = Host_ByID(infoPtr->hostID);
  418.     if (hostPtr == (Host_Entry *) NULL) {
  419.     syslog(LOG_WARNING, 
  420.            "error in Host_ByID(%d).\n", infoPtr->hostID);
  421.     return;
  422.     }
  423.     /*
  424.      * Copy the name of the host, up to HOST_NAME_SIZE or the first
  425.      * '.' so we don't output the domain.
  426.      */
  427.     for (sp = hostName, hp = hostPtr->name, i = 0;
  428.      i < HOST_NAME_SIZE && *hp != '\0' && (!stripDomain || *hp != '.');
  429.      sp++, hp++, i++) {
  430.     *sp = *hp;
  431.     }
  432.     *sp = '\0';
  433.     
  434.  
  435.     /*
  436.      * See if the entry is out of date.  (Assume that anything updated
  437.      * after the current time is fairly recent and is caused by clock
  438.      * skew, so negative diffs are okay.)
  439.      */
  440.     state = infoPtr->state;
  441.     if (state == MIG_HOST_DOWN) {
  442.     diff = currentTime.tv_sec - infoPtr->loadVec.timestamp;
  443.     } else {
  444.     /*
  445.      * We want to know how long the machine has been up.
  446.      */
  447.     diff = infoPtr->loadVec.timestamp - infoPtr->bootTime;
  448.     if (diff < 0) {
  449.         (void) fprintf(stderr,
  450.                "Change was made before boot time??  modTime %d, bootTime %d, host %s.\n",
  451.                infoPtr->loadVec.timestamp, infoPtr->bootTime,
  452.                hostPtr->name);
  453.         diff = 0;
  454.     }
  455.     }
  456.         
  457.  
  458.     Time_ToAscii(diff, 1, timeStr);
  459.     timeStr[SECOND_OFFSET] = '\0';
  460.  
  461.     /*
  462.      * We allow migration if it's the right version,
  463.      * the file says to allow it, the entry in the
  464.      * file is current, we're exporting, and it is the same machine type.
  465.      * We're only concerned with normal priority processes, so we check
  466.      * against the max count if the host is partially in use.
  467.      */
  468.     migOK = ' ';
  469.     if (state != MIG_HOST_DOWN) {
  470.     if (infoPtr->loadVec.allowMigration) {
  471.         if ((state == MIG_HOST_PART_USED) || (state == MIG_HOST_FULL)) {
  472.         strcpy(stateStr, "hasmig");
  473.         } else {
  474.         strcpy(stateStr, "avail");
  475.         }
  476.         if (!strcmp(hostPtr->machType, machType)) {
  477.         if (infoPtr->migVersion != migVersion) {
  478.             strcpy(stateStr, "refuses");
  479.         } else if (hostPtr->id != hostID &&
  480.                state != MIG_HOST_FULL &&
  481.                infoPtr->foreign[MIG_NORMAL_PRIORITY] <
  482.                infoPtr->maxProcs) {
  483.             migOK = '*';
  484.         }
  485.         }
  486.     } else if (infoPtr->state == MIG_HOST_REFUSES) {
  487.         strcpy(stateStr, "refuses");
  488.     } else {
  489.         strcpy(stateStr, "inuse");
  490.     }
  491.     strcpy(upStr, "up");
  492.     } else {
  493.     strcpy(upStr, "down");
  494.     stateStr[0] = '\0';
  495.     }
  496.     (void) fprintf(stdout,
  497.            "%16s%c  %6s %4s %s %7s",
  498.            hostName, migOK,
  499.            hostPtr->machType,
  500.            upStr,
  501.            timeStr,
  502.            stateStr);
  503.     if (state != MIG_HOST_DOWN) {
  504.     (void) fprintf(stdout,
  505.                " %5.2lf %5.2lf %5.2lf",
  506.                infoPtr->loadVec.lengths[0], infoPtr->loadVec.lengths[1],
  507.                infoPtr->loadVec.lengths[2]);
  508.     if ((state != MIG_HOST_ACTIVE) || (infoPtr->loadVec.noInput > 60)) {
  509.         Time_ToAscii(infoPtr->loadVec.noInput, 1, idleTime);
  510.         idleTime[SECOND_OFFSET] = '\0';
  511.         for (idlePtr = idleTime; *idlePtr == ' '; idlePtr++) {
  512.         }
  513.         fprintf(stdout, " (%s)", idlePtr);
  514.     }
  515.     }
  516.     (void) fprintf(stdout, "\n");
  517. }
  518.  
  519.  
  520.  
  521. /*
  522.  *----------------------------------------------------------------------
  523.  *
  524.  * ZapHostInfo --
  525.  *
  526.  *    Zero out the information for a host.
  527.  *
  528.  * Results:
  529.  *    None.
  530.  *
  531.  * Side effects:
  532.  *    The global database is modified.
  533.  *
  534.  *----------------------------------------------------------------------
  535.  */
  536.  
  537. static void
  538. ZapHostInfo(hostname)
  539.     char *hostname;
  540. {
  541.     ReturnStatus status;
  542.     Mig_Info info;
  543.     Host_Entry *hostPtr;
  544.     
  545.  
  546.     hostPtr = Host_ByName(hostname);
  547.     if (hostPtr == (Host_Entry *) NULL) {
  548.     (void) fprintf(stderr, "ZapHostInfo: couldn't get info for %s.\n",
  549.                hostname);
  550.     return;
  551.     }
  552.     status = Mig_DeleteHost(hostPtr->id);
  553.     if (status != 0) {
  554.     perror("Error in Mig_DeleteHost");
  555.     }
  556. }
  557. @
  558.  
  559.  
  560. 1.12
  561. log
  562. @changes for printing idle time info and available hosts when they're
  563. partially used (for background jobs).
  564. @
  565. text
  566. @d17 1
  567. a17 1
  568. static char rcsid[] = "$Header: /sprite/src/cmds/loadavg/RCS/loadavg.c,v 1.11 90/04/09 10:17:46 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  569. d385 6
  570. a390 6
  571.     if (((state == MIG_HOST_PART_USED) &&
  572.          (infoPtr->foreign[MIG_NORMAL_PRIORITY] == infoPtr->maxProcs)) ||
  573.         (state == MIG_HOST_FULL)) {
  574.         strcpy(stateStr, "hasmig");
  575.     } else if (infoPtr->loadVec.allowMigration) {
  576.         strcpy(stateStr, "avail");
  577. d394 4
  578. a397 1
  579.         } else if (hostPtr->id != hostID) {
  580. @
  581.  
  582.  
  583. 1.11
  584. log
  585. @major rework for new interface for migd.
  586. @
  587. text
  588. @d17 1
  589. a17 1
  590. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.10 89/08/22 22:58:47 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  591. d380 2
  592. d385 3
  593. a387 1
  594.     if (state == MIG_HOST_PART_USED || state == MIG_HOST_FULL) {
  595. d416 5
  596. a420 2
  597.     int doIdle;
  598.     if (state != MIG_HOST_ACTIVE) {
  599. a424 9
  600.         doIdle = 1;
  601.     } else {
  602.         doIdle = 0;
  603.     }
  604.     (void) fprintf(stdout,
  605.                " %5.2lf %5.2lf %5.2lf",
  606.                infoPtr->loadVec.lengths[0], infoPtr->loadVec.lengths[1],
  607.                infoPtr->loadVec.lengths[2]);
  608.     if (doIdle) {
  609. @
  610.  
  611.  
  612. 1.10
  613. log
  614. @print "!" for machines w/ allowable migration but of different type/version
  615. @
  616. text
  617. @d4 1
  618. a4 4
  619.  *    Maintain load average information on a per-host basis.  This program
  620.  *    may be invoked as a daemon (to update global state on a regular basis)
  621.  *    or as a stand-alone program (to return the load of the local host or
  622.  *     all hosts on the network).
  623. d6 1
  624. a6 1
  625.  * Copyright 1987, 1988 Regents of the University of California
  626. d17 1
  627. a17 1
  628. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.9 89/07/31 17:51:58 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  629. d21 7
  630. a27 7
  631. #include "loadavg.h"
  632.  
  633. #include "sprite.h"
  634. #include "option.h"
  635. #include "host.h"
  636. #include "sysStats.h"
  637.  
  638. d30 1
  639. a36 60
  640. /*
  641.  * Constants specific to gathering load average statistics.  (The weights may
  642.  * be modified with -D options but are not user-specifiable on the
  643.  * command line.)  The LOAD_INTERVAL is the number of seconds between sampling
  644.  * the utilization and ready queue lengths, and the WRITE_INTERVAL is the
  645.  * maximum number of seconds that may pass between updating the shared data
  646.  * file.  (The private data file is updated on each iteration.)
  647.  * For example, to write once per minute if the state of a machine doesn't
  648.  * change between idle and inUse, WRITE_INTERVAL would be (12 * LOAD_INTERVAL).
  649.  * To write every time, set it equal to LOAD_INTERVAL.  TIME_OUT is the
  650.  * default time to allow a host before assuming it's down.
  651.  */
  652.  
  653. #ifndef LOAD_INTERVAL
  654. #define LOAD_INTERVAL 5
  655. #endif 
  656.  
  657. #ifndef WRITE_INTERVAL
  658. #define WRITE_INTERVAL (12 * LOAD_INTERVAL)
  659. #endif
  660.  
  661. #ifndef TIME_OUT
  662. #define TIME_OUT 180
  663. #endif
  664.  
  665. #define WEIGHT1 0.9200444146293232     /* exp(-1/12) */
  666. #define WEIGHT2 0.9834714538216174     /* exp(-1/60) */
  667. #define WEIGHT3 0.9944598480048967     /* exp(-1/180) */
  668.  
  669. double weights[] = {WEIGHT1, WEIGHT2, WEIGHT3};
  670.  
  671.  
  672. /*
  673.  * Define arbitrary thresholds (see loadavg.h).
  674.  *
  675.  * All load values must be below their corresponding THRESHOLD_LOW* to
  676.  * start accepting foreign processes, but once they are being
  677.  * accepted, there are different thresholds for each average: if any
  678.  * one of them is exceeded, stop aceepting foreign processes.
  679.  *
  680.  * INPUT_THRESHOLD is the number of seconds that a node must
  681.  * be idle for it to accept migrated processes.  (Set to a low value for
  682.  * testing.)
  683.  */
  684.  
  685.  
  686. #define THRESHOLD_LOW0 0.5
  687. #define THRESHOLD_LOW1 1.0
  688. #define THRESHOLD_LOW2 1.5
  689. #define THRESHOLD_HIGH0 2.0
  690. #define THRESHOLD_HIGH1 1.5
  691. #define THRESHOLD_HIGH2 1.0
  692. #define INPUT_THRESHOLD 300
  693.  
  694. Thresholds thresholds = {
  695.     INPUT_THRESHOLD,
  696.     {THRESHOLD_LOW0, THRESHOLD_LOW1, THRESHOLD_LOW2},
  697.     {THRESHOLD_HIGH0, THRESHOLD_HIGH1, THRESHOLD_HIGH2}
  698. };
  699.  
  700. a38 1
  701. int runDaemon = 0;
  702. a39 5
  703. int verbose = 0;
  704. int loadInterval = LOAD_INTERVAL;
  705. int writeInterval = WRITE_INTERVAL;
  706. int timeOut = TIME_OUT;
  707. int getIdleNode = 0;
  708. a40 3
  709. int neverAccept = 0;
  710. int migVersion = 0;
  711. int alwaysAccept = 0;
  712. a42 11
  713. int useKernelIdleTime = 1;
  714.  
  715. /*
  716.  * Both of these are temporary areas to hold changes in the default values.
  717.  * If untouched by options, then they aren't used.
  718.  */
  719.  
  720. char *lowThresholdString = NULL;
  721. char *highThresholdString = NULL;
  722.  
  723. char *myName = NULL;
  724. a50 10
  725.     {OPT_TRUE, "i", (char *)&getIdleNode,
  726.          "Get the hostID of an idle node."},
  727.     {OPT_TRUE, "d", (char *)&runDaemon,
  728.     "Run as a daemon and report load information to the global file."},
  729.     {OPT_FALSE, "K", (char *)&useKernelIdleTime,
  730.          "Try not to use the internal kernel variable to keep track of idle time."},
  731.     {OPT_TRUE, "r", (char *)&neverAccept,
  732.          "Claim to refuse migrations regardless of load or idle time."},
  733.     {OPT_TRUE, "R", (char *)&alwaysAccept,
  734.          "Claim to accept migrations regardless of load or idle time."},
  735. a52 16
  736.     {OPT_TRUE, "v", (char *)&verbose,
  737.          "Enable extra information messages."},
  738.     {OPT_INT, "M", (char *)&migVersion,
  739.     "Override the value of the kernel migration level to store in the database."},
  740.     {OPT_INT, "I", (char *)&loadInterval,
  741.     "Interval between iterations for getting load info."},
  742.     {OPT_INT, "w", (char *)&writeInterval,
  743.          "Maximum interval between outputting load info."},
  744.     {OPT_INT, "W", (char *)&timeOut,
  745.          "Maximum time during which info is valid without update."},
  746.     {OPT_INT, "N", (char *)&thresholds.noInput,
  747.          "Minimum idle time to allow foreign procs."},
  748.     {OPT_STRING, "t", (char *)&lowThresholdString,
  749.          "Set of minimum thresholds before accepting migration, once refused (as in the form '-t \"0.5 1.0 1.5\"')."},
  750.     {OPT_STRING, "T", (char *)&highThresholdString,
  751.          "Set of maximum thresholds before refusing migration, once allowed (as in the form '-T \"2.0 1.5 1.0\"')."},
  752. a58 14
  753.  * Define a few possible states of machines.  If a host hasn't updated
  754.  * its entry recently, or if the entry is nonsensical, we mark the host
  755.  * as DOWN.  If it's up but active, it's UP, and if it's up and idle for
  756.  * some period of time, it's MIG_ALLOWED.
  757.  */
  758. typedef enum {
  759.     DOWN,
  760.     UP,
  761.     MIG_ALLOWED
  762. } MachineState;
  763.  
  764. #define HOST_NAME_LENGTH 64
  765.  
  766. /*
  767. d63 1
  768. d66 2
  769. d69 1
  770. a69 4
  771. int numLowPris;
  772. #ifdef INTERIM
  773. int oldKernel = 0;
  774. #endif /* INTERIM */
  775. d89 1
  776. a89 1
  777.  *    The global var. 'hostID' is initialized.
  778. d123 1
  779. a123 1
  780.      * Default operation is to get the local load, using a global data file.
  781. d126 1
  782. a126 2
  783.     if (! (runDaemon || getIdleNode || getLoad || allHosts ||
  784.        zapHostInfo || forceEvict)) {
  785. a135 33
  786.     if (lowThresholdString) {
  787.     numScanned = sscanf(lowThresholdString, "%lf %lf %lf",
  788.                    &thresholds.min[0], &thresholds.min[1],
  789.                    &thresholds.min[2]);
  790.     if (numScanned < 3) {
  791.         (void) fprintf(stderr, "%s: Invalid thresholds '%s'.\n", myName,
  792.                lowThresholdString);
  793.         exit(FAILURE);
  794.     }
  795.     }
  796.  
  797.     if (highThresholdString) {
  798.     numScanned = sscanf(highThresholdString, "%lf %lf %lf",
  799.                    &thresholds.max[0], &thresholds.max[1],
  800.                    &thresholds.max[2]);
  801.     if (numScanned < 3) {
  802.         (void) fprintf(stderr, "%s: Invalid thresholds '%s'.\n", myName,
  803.                highThresholdString);
  804.         exit(FAILURE);
  805.     }
  806.     }
  807.  
  808.     if (writeInterval < loadInterval) {
  809.     writeInterval = loadInterval;
  810.     }
  811.  
  812.     if (debug && runDaemon) {
  813.     (void) fprintf(stderr, "Weights are %f, %f, %f.\n",
  814.                weights[0], weights[1], weights[2]);
  815.     }
  816.  
  817.     openlog("loadavg", LOG_PID, runDaemon? LOG_DAEMON : LOG_USER);
  818.     
  819. a139 1
  820.     syslog(LOG_ERR, "error getting hostname.\n");
  821. d145 1
  822. a145 1
  823.     syslog(LOG_ERR, "error getting host information for '%s'.\n",
  824. d159 6
  825. a164 8
  826.     if (!migVersion){
  827.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_GET_VERSION,
  828.                (Address) &migVersion);
  829.     if (status != SUCCESS) {
  830.         syslog(LOG_ERR, "Error in Sys_Stats getting migration version: %s\n",
  831.            Stat_GetMsg(status));
  832.         exit(Compat_MapCode(status));
  833.     }
  834. d172 3
  835. a174 5
  836.     if (debug) {
  837.         (void) fprintf(stderr,
  838.                "%s: warning: error in Sys_Stats getting migration state.\n",
  839.                myName);
  840.     }
  841. a175 3
  842. #ifdef INTERIM
  843.     oldKernel = 1;
  844. #endif /* INTERIM */
  845. a192 15
  846.     if (runDaemon) {
  847.     RunDaemon();
  848.     }
  849.     if (getIdleNode) {
  850.     host = Mig_GetIdleNode();
  851.     if (host < 0) {
  852.         perror("Error in Mig_GetIdleNode");
  853.         exit(1);
  854.     } else if (host != 0) {
  855.         (void) printf("%d\n", host);
  856.         (void) Mig_Done(host);
  857.     } else if (verbose) {
  858.         (void) fprintf(stderr, "No idle node found.\n");
  859.     }
  860.     }
  861. d205 4
  862. a208 1
  863.     int numEvicted = FindForeign(EVICT, 1);
  864. d210 1
  865. d240 2
  866. d248 6
  867. d267 1
  868. d270 1
  869. a270 10
  870.     infoPtr = &infoArray[i];
  871.     if (infoPtr->timestamp != 0) {
  872.         if (i != infoPtr->hostID) {
  873.         (void) fprintf(stderr,
  874.                    "ListHosts: mismatch between counter (%d) and value in data file (%d).\n",
  875.                    i, infoPtr->hostID);
  876.         exit(1);
  877.         }
  878.         OutputStatus(infoPtr);
  879.     }
  880. a274 1
  881.  
  882. d318 1
  883. a318 1
  884.     MachineState state;
  885. d320 1
  886. d322 3
  887. a330 1
  888.     char stateChar;
  889. d355 3
  890. a357 4
  891.     state = UP;
  892.     diff = currentTime.tv_sec - infoPtr->timestamp;
  893.     if (diff > timeOut) {
  894.     state = DOWN;
  895. d360 1
  896. a360 1
  897.      * Now we want to know how long the machine has been up.
  898. d362 1
  899. a362 1
  900.     diff = infoPtr->timestamp - infoPtr->bootTime;
  901. d365 3
  902. a367 3
  903.                "Change was made before boot time??  modTime %d, bootTime %d.\n",
  904.                infoPtr->timestamp, infoPtr->bootTime);
  905.         state = DOWN;
  906. d377 2
  907. a378 1
  908.      * We allow migration if the file says to allow it, the entry in the
  909. d381 12
  910. a392 12
  911.     if (state == UP && infoPtr->allowMigration &&
  912.     strcmp(hostPtr->machType, machType) == 0 &&
  913.     ((kernelState & PROC_MIG_EXPORT_ALL) == PROC_MIG_EXPORT_ALL) &&
  914.     infoPtr->migVersion == migVersion) {
  915.     state = MIG_ALLOWED;
  916.     }
  917.     if (state != DOWN) {
  918.     if (state == MIG_ALLOWED) {
  919.         if (infoPtr->foreignProcs > 0) {
  920.         stateChar = '+';
  921.         } else {
  922.         stateChar = '*';
  923. d394 2
  924. a395 4
  925.     } else if (infoPtr->foreignProcs > 0) {
  926.         stateChar = '-';
  927.     } else if (infoPtr->allowMigration > 0) {
  928.         stateChar = '!';
  929. d397 1
  930. a397 1
  931.         stateChar = ' ';
  932. d399 1
  933. d401 2
  934. a402 1
  935.     stateChar = ' ';
  936. d405 2
  937. a406 2
  938.            "%16s%c %6s  %s %s",
  939.            hostName, stateChar,
  940. d408 14
  941. a421 4
  942.            (state == DOWN) ? "down" : "  up",
  943.            timeStr);
  944.     if (state != DOWN) {
  945.     Time_ToAscii(infoPtr->noInput, 1, idleTime);
  946. d423 6
  947. a428 3
  948.                " %5.2lf %5.2lf %5.2lf  (idle %s)",
  949.                infoPtr->lengths[0], infoPtr->lengths[1],
  950.                infoPtr->lengths[2], idleTime);
  951. d433 1
  952. a457 1
  953.     Db_Handle sharedHandle;
  954. d466 1
  955. a466 16
  956.     if (debug) {
  957.     (void) fprintf(stderr, "Opening shared database.\n");
  958.     (void) fflush(stderr);
  959.     }
  960.     status = Mig_OpenInfo(MIG_SHARED, 1, &sharedHandle);
  961.     if (status != 0) {
  962.     perror("Error in Mig_OpenInfo (shared)");
  963.     exit(1);
  964.     }
  965.     bzero((Address) &info, sizeof(info));
  966.     status = Mig_UpdateInfo(hostPtr->id, &info, &sharedHandle, 1);
  967.     if (status != 0) {
  968.     perror("Error in Mig_UpdateInfo (shared)");
  969.     exit(1);
  970.     }
  971.     status = Db_Close(&sharedHandle);
  972. d468 1
  973. a468 2
  974.     perror("Error in Db_Close");
  975.     exit(1);
  976. @
  977.  
  978.  
  979. 1.9
  980. log
  981. @single '.')
  982. >> use the kernel idle time by default, but changes to support statting 
  983. if only it would work without requiring exclusive access
  984. @
  985. text
  986. @d20 1
  987. a20 1
  988. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.8 89/07/13 23:24:42 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  989. d569 2
  990. @
  991.  
  992.  
  993. 1.8
  994. log
  995. @Don't charge low priority processes against the load average when deciding whether to accept migrations
  996. @
  997. text
  998. @d20 1
  999. a20 1
  1000. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.7 89/06/15 22:54:53 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1001. d114 1
  1002. d137 2
  1003. @
  1004.  
  1005.  
  1006. 1.7
  1007. log
  1008. @check against verbose mode.  reset count to 0 when evicting.
  1009. @
  1010. text
  1011. @d20 1
  1012. a20 1
  1013. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.6 89/05/04 15:49:03 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1014. d185 1
  1015. @
  1016.  
  1017.  
  1018. 1.6
  1019. log
  1020. @changed to use the kernel state variable for import/export permissions.
  1021. print machine type of hosts in listing of loads.  strip domain names.
  1022. print "-" next to hosts that are not allowing migration from us but
  1023. which have foreign processes.
  1024. @
  1025. text
  1026. @d20 1
  1027. a20 1
  1028. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.5 89/03/17 12:42:17 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1029. d503 1
  1030. a503 1
  1031.     syslog(LOG_ERR, 
  1032. d505 1
  1033. a505 1
  1034.     exit(1);
  1035. @
  1036.  
  1037.  
  1038. 1.5
  1039. log
  1040. @removed (double) cast for constants since new gcc broke.  other
  1041. minor changes to procedure args.
  1042. @
  1043. text
  1044. @d20 1
  1045. a20 1
  1046. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.4 88/12/21 16:01:05 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1047. a107 1
  1048. int forkChild = 0;
  1049. d113 1
  1050. d130 2
  1051. a151 1
  1052.     {OPT_TRUE, "F", (char *)&forkChild, "Fork off daemons."},
  1053. d184 4
  1054. d316 15
  1055. a330 6
  1056.         if (debug) {
  1057.         (void) fprintf(stderr,
  1058.                    "%s: warning: error in Sys_Stats getting version.\n",
  1059.                    myName);
  1060.         }
  1061.         migVersion = 1;
  1062. d332 4
  1063. d338 3
  1064. a340 2
  1065.         (void) fprintf(stderr, "My hostID is %d.  machType is %s.\n", hostID,
  1066.         machType);
  1067. d491 6
  1068. a496 2
  1069.     static char idleTime[TIME_STR_LEN];
  1070.     static char timeStr[TIME_STR_LEN];
  1071. d507 11
  1072. d548 1
  1073. a548 1
  1074.      * file is current, and it is the same machine type.
  1075. d552 1
  1076. d557 8
  1077. a564 4
  1078.     if (infoPtr->foreignProcs > 0) {
  1079.         stateChar = '+';
  1080.     } else if (state == MIG_ALLOWED) {
  1081.         stateChar = '*';
  1082. d572 3
  1083. a574 2
  1084.            "%24s%c %s %s",
  1085.            hostPtr->name, stateChar,
  1086. @
  1087.  
  1088.  
  1089. 1.4
  1090. log
  1091. @allow eviction based on command line argument.  compare migVersion before
  1092. noting that another host is available (in "rup" format).
  1093. @
  1094. text
  1095. @d20 1
  1096. a20 1
  1097. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.3 88/11/19 15:54:09 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1098. d64 3
  1099. a66 3
  1100. #define WEIGHT1 (double) 0.9200444146293232     /* exp(-1/12) */
  1101. #define WEIGHT2 (double) 0.9834714538216174     /* exp(-1/60) */
  1102. #define WEIGHT3 (double) 0.9944598480048967     /* exp(-1/180) */
  1103. d141 1
  1104. a141 1
  1105.          "Report to stderr when no idle nodes available."},
  1106. d281 2
  1107. d287 1
  1108. a287 1
  1109.     syslog(LOG_ERR, "%s: error getting hostname.\n", myName);
  1110. d293 2
  1111. a294 2
  1112.     syslog(LOG_ERR, "%s: error getting host information for '%s'.\n",
  1113.            myName, hostname);
  1114. d361 1
  1115. a361 1
  1116.     int numEvicted = FindForeign(EVICT);
  1117. d481 1
  1118. a481 1
  1119.            "%s: error in Host_ByID(%d).\n", myName, infoPtr->hostID);
  1120. d590 1
  1121. a590 1
  1122.     status = Mig_UpdateInfo(hostPtr->id, &info, &sharedHandle);
  1123. @
  1124.  
  1125.  
  1126. 1.3
  1127. log
  1128. @arguments to override idle time considerations to always or never accept
  1129. foreign processes.  check for machine being down before printing "+".
  1130. @
  1131. text
  1132. @d20 1
  1133. a20 1
  1134. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.2 88/11/15 12:14:08 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1135. d29 1
  1136. d113 1
  1137. d138 1
  1138. d187 1
  1139. a188 1
  1140.  
  1141. d223 6
  1142. a228 1
  1143.     myName = argv[0];
  1144. d239 9
  1145. a247 2
  1146.     if (! (runDaemon || getIdleNode || getLoad || zapHostInfo)) {
  1147.     getLoad = 1;
  1148. d302 15
  1149. d347 7
  1150. a353 10
  1151.     if (getLoad) {
  1152.     if (allHosts) {
  1153.         ListHosts();
  1154.     } else {
  1155.         infoPtr = Mig_GetInfo((int) PROC_MY_HOSTID);
  1156.         if (infoPtr == (Mig_Info *) NULL) {
  1157.         perror("Error in Mig_GetInfo");
  1158.         exit(1);
  1159.         }
  1160.         OutputStatus(infoPtr);
  1161. d355 1
  1162. d358 4
  1163. d515 2
  1164. a516 1
  1165.     strcmp(hostPtr->machType, machType) == 0) {
  1166. @
  1167.  
  1168.  
  1169. 1.2
  1170. log
  1171. @got rid of obsolete declarations.
  1172. @
  1173. text
  1174. @d20 1
  1175. a20 1
  1176. static char rcsid[] = "$Header: /a/newcmds/loadavg/RCS/loadavg.c,v 1.1 88/11/14 13:28:37 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
  1177. d109 3
  1178. d132 4
  1179. d139 2
  1180. d312 1
  1181. d364 1
  1182. a364 1
  1183.     maxSize = MAX_NUM_HOSTS * sizeof(Mig_Info);
  1184. d366 1
  1185. a366 1
  1186.     numRecs = Mig_GetAllInfo(infoArray, MAX_NUM_HOSTS);
  1187. d486 8
  1188. a493 4
  1189.     if (infoPtr->foreignProcs > 0) {
  1190.     stateChar = '+';
  1191.     } else if (state == MIG_ALLOWED) {
  1192.     stateChar = '*';
  1193. @
  1194.  
  1195.  
  1196. 1.1
  1197. log
  1198. @Initial revision
  1199. @
  1200. text
  1201. @d20 1
  1202. a20 1
  1203. static char rcsid[] = "$Header: loadAvg.c,v 2.12 88/06/23 11:46:48 douglis Exp $ SPRITE (Berkeley)";
  1204. a430 1
  1205.     char *upStr;
  1206. @
  1207.